
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>django.template.base &#8212; Django 1.11.22.dev20190603194737 documentation</title>
    <link rel="stylesheet" href="../../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../../_static/language_data.js"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />



 
<script type="text/javascript" src="../../../templatebuiltins.js"></script>
<script type="text/javascript">
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);
</script>


  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../../index.html">Django 1.11.22.dev20190603194737 documentation</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../../index.html">Home</a>  |
        <a title="Table of contents" href="../../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../../genindex.html">Index</a>  |
        <a title="Module index" href="../../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    <a href="../../index.html" title="Module code" accesskey="U">up</a></div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="_modules-django-template-base">
            
  <h1>Source code for django.template.base</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">This is the Django template system.</span>

<span class="sd">How it works:</span>

<span class="sd">The Lexer.tokenize() function converts a template string (i.e., a string containing</span>
<span class="sd">markup with custom template tags) to tokens, which can be either plain text</span>
<span class="sd">(TOKEN_TEXT), variables (TOKEN_VAR) or block statements (TOKEN_BLOCK).</span>

<span class="sd">The Parser() class takes a list of tokens in its constructor, and its parse()</span>
<span class="sd">method returns a compiled template -- which is, under the hood, a list of</span>
<span class="sd">Node objects.</span>

<span class="sd">Each Node is responsible for creating some sort of output -- e.g. simple text</span>
<span class="sd">(TextNode), variable values in a given context (VariableNode), results of basic</span>
<span class="sd">logic (IfNode), results of looping (ForNode), or anything else. The core Node</span>
<span class="sd">types are TextNode, VariableNode, IfNode and ForNode, but plugin modules can</span>
<span class="sd">define their own custom node types.</span>

<span class="sd">Each Node has a render() method, which takes a Context and returns a string of</span>
<span class="sd">the rendered node. For example, the render() method of a Variable Node returns</span>
<span class="sd">the variable&#39;s value as a string. The render() method of a ForNode returns the</span>
<span class="sd">rendered output of whatever was inside the loop, recursively.</span>

<span class="sd">The Template class is a convenient wrapper that takes care of template</span>
<span class="sd">compilation and rendering.</span>

<span class="sd">Usage:</span>

<span class="sd">The only thing you should ever use directly in this file is the Template class.</span>
<span class="sd">Create a compiled template object with a template_string, then call render()</span>
<span class="sd">with a context. In the compilation stage, the TemplateSyntaxError exception</span>
<span class="sd">will be raised if the template doesn&#39;t have proper syntax.</span>

<span class="sd">Sample code:</span>

<span class="sd">&gt;&gt;&gt; from django import template</span>
<span class="sd">&gt;&gt;&gt; s = &#39;&lt;html&gt;{% if test %}&lt;h1&gt;{{ varvalue }}&lt;/h1&gt;{% endif %}&lt;/html&gt;&#39;</span>
<span class="sd">&gt;&gt;&gt; t = template.Template(s)</span>

<span class="sd">(t is now a compiled template, and its render() method can be called multiple</span>
<span class="sd">times with multiple contexts)</span>

<span class="sd">&gt;&gt;&gt; c = template.Context({&#39;test&#39;:True, &#39;varvalue&#39;: &#39;Hello&#39;})</span>
<span class="sd">&gt;&gt;&gt; t.render(c)</span>
<span class="sd">&#39;&lt;html&gt;&lt;h1&gt;Hello&lt;/h1&gt;&lt;/html&gt;&#39;</span>
<span class="sd">&gt;&gt;&gt; c = template.Context({&#39;test&#39;:False, &#39;varvalue&#39;: &#39;Hello&#39;})</span>
<span class="sd">&gt;&gt;&gt; t.render(c)</span>
<span class="sd">&#39;&lt;html&gt;&lt;/html&gt;&#39;</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">unicode_literals</span>

<span class="kn">import</span> <span class="nn">inspect</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">warnings</span>

<span class="kn">from</span> <span class="nn">django.template.context</span> <span class="k">import</span> <span class="p">(</span>  <span class="c1"># NOQA: imported for backwards compatibility</span>
    <span class="n">BaseContext</span><span class="p">,</span> <span class="n">Context</span><span class="p">,</span> <span class="n">ContextPopException</span><span class="p">,</span> <span class="n">RequestContext</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils</span> <span class="k">import</span> <span class="n">six</span>
<span class="kn">from</span> <span class="nn">django.utils.deprecation</span> <span class="k">import</span> <span class="p">(</span>
    <span class="n">DeprecationInstanceCheck</span><span class="p">,</span> <span class="n">RemovedInDjango20Warning</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils.encoding</span> <span class="k">import</span> <span class="p">(</span>
    <span class="n">force_str</span><span class="p">,</span> <span class="n">force_text</span><span class="p">,</span> <span class="n">python_2_unicode_compatible</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils.formats</span> <span class="k">import</span> <span class="n">localize</span>
<span class="kn">from</span> <span class="nn">django.utils.html</span> <span class="k">import</span> <span class="n">conditional_escape</span><span class="p">,</span> <span class="n">escape</span>
<span class="kn">from</span> <span class="nn">django.utils.inspect</span> <span class="k">import</span> <span class="n">getargspec</span>
<span class="kn">from</span> <span class="nn">django.utils.safestring</span> <span class="k">import</span> <span class="p">(</span>
    <span class="n">EscapeData</span><span class="p">,</span> <span class="n">SafeData</span><span class="p">,</span> <span class="n">mark_for_escaping</span><span class="p">,</span> <span class="n">mark_safe</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils.text</span> <span class="k">import</span> <span class="p">(</span>
    <span class="n">get_text_list</span><span class="p">,</span> <span class="n">smart_split</span><span class="p">,</span> <span class="n">unescape_string_literal</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">django.utils.timezone</span> <span class="k">import</span> <span class="n">template_localtime</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="k">import</span> <span class="n">pgettext_lazy</span><span class="p">,</span> <span class="n">ugettext_lazy</span>

<span class="kn">from</span> <span class="nn">.exceptions</span> <span class="k">import</span> <span class="n">TemplateSyntaxError</span>

<span class="n">TOKEN_TEXT</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">TOKEN_VAR</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">TOKEN_BLOCK</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">TOKEN_COMMENT</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">TOKEN_MAPPING</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">TOKEN_TEXT</span><span class="p">:</span> <span class="s1">&#39;Text&#39;</span><span class="p">,</span>
    <span class="n">TOKEN_VAR</span><span class="p">:</span> <span class="s1">&#39;Var&#39;</span><span class="p">,</span>
    <span class="n">TOKEN_BLOCK</span><span class="p">:</span> <span class="s1">&#39;Block&#39;</span><span class="p">,</span>
    <span class="n">TOKEN_COMMENT</span><span class="p">:</span> <span class="s1">&#39;Comment&#39;</span><span class="p">,</span>
<span class="p">}</span>

<span class="c1"># template syntax constants</span>
<span class="n">FILTER_SEPARATOR</span> <span class="o">=</span> <span class="s1">&#39;|&#39;</span>
<span class="n">FILTER_ARGUMENT_SEPARATOR</span> <span class="o">=</span> <span class="s1">&#39;:&#39;</span>
<span class="n">VARIABLE_ATTRIBUTE_SEPARATOR</span> <span class="o">=</span> <span class="s1">&#39;.&#39;</span>
<span class="n">BLOCK_TAG_START</span> <span class="o">=</span> <span class="s1">&#39;{%&#39;</span>
<span class="n">BLOCK_TAG_END</span> <span class="o">=</span> <span class="s1">&#39;%}&#39;</span>
<span class="n">VARIABLE_TAG_START</span> <span class="o">=</span> <span class="s1">&#39;{{&#39;</span>
<span class="n">VARIABLE_TAG_END</span> <span class="o">=</span> <span class="s1">&#39;}}&#39;</span>
<span class="n">COMMENT_TAG_START</span> <span class="o">=</span> <span class="s1">&#39;{#&#39;</span>
<span class="n">COMMENT_TAG_END</span> <span class="o">=</span> <span class="s1">&#39;#}&#39;</span>
<span class="n">TRANSLATOR_COMMENT_MARK</span> <span class="o">=</span> <span class="s1">&#39;Translators&#39;</span>
<span class="n">SINGLE_BRACE_START</span> <span class="o">=</span> <span class="s1">&#39;{&#39;</span>
<span class="n">SINGLE_BRACE_END</span> <span class="o">=</span> <span class="s1">&#39;}&#39;</span>

<span class="c1"># what to report as the origin for templates that come from non-loader sources</span>
<span class="c1"># (e.g. strings)</span>
<span class="n">UNKNOWN_SOURCE</span> <span class="o">=</span> <span class="s1">&#39;&lt;unknown source&gt;&#39;</span>

<span class="c1"># match a variable or block tag and capture the entire tag, including start/end</span>
<span class="c1"># delimiters</span>
<span class="n">tag_re</span> <span class="o">=</span> <span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;(</span><span class="si">%s</span><span class="s1">.*?</span><span class="si">%s</span><span class="s1">|</span><span class="si">%s</span><span class="s1">.*?</span><span class="si">%s</span><span class="s1">|</span><span class="si">%s</span><span class="s1">.*?</span><span class="si">%s</span><span class="s1">)&#39;</span> <span class="o">%</span>
          <span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">BLOCK_TAG_START</span><span class="p">),</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">BLOCK_TAG_END</span><span class="p">),</span>
           <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">VARIABLE_TAG_START</span><span class="p">),</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">VARIABLE_TAG_END</span><span class="p">),</span>
           <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">COMMENT_TAG_START</span><span class="p">),</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">COMMENT_TAG_END</span><span class="p">))))</span>

<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;django.template&#39;</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">TemplateEncodingError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
    <span class="k">pass</span>


<span class="nd">@python_2_unicode_compatible</span>
<span class="k">class</span> <span class="nc">VariableDoesNotExist</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="p">()):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">params</span> <span class="o">=</span> <span class="n">params</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">%</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">force_text</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="s1">&#39;replace&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span><span class="p">)</span>


<div class="viewcode-block" id="Origin"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.Origin">[docs]</a><span class="k">class</span> <span class="nc">Origin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">template_name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">loader</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">template_name</span> <span class="o">=</span> <span class="n">template_name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">loader</span> <span class="o">=</span> <span class="n">loader</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>

    <span class="k">def</span> <span class="nf">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">Origin</span><span class="p">):</span>
            <span class="k">return</span> <span class="kc">False</span>

        <span class="k">return</span> <span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">name</span> <span class="ow">and</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">loader</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">loader</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="nf">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">loader_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="p">:</span>
            <span class="k">return</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">.</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
            <span class="p">)</span></div>


<span class="k">class</span> <span class="nc">StringOrigin</span><span class="p">(</span><span class="n">six</span><span class="o">.</span><span class="n">with_metaclass</span><span class="p">(</span><span class="n">DeprecationInstanceCheck</span><span class="p">,</span> <span class="n">Origin</span><span class="p">)):</span>
    <span class="n">alternative</span> <span class="o">=</span> <span class="s1">&#39;django.template.Origin&#39;</span>
    <span class="n">deprecation_warning</span> <span class="o">=</span> <span class="n">RemovedInDjango20Warning</span>


<div class="viewcode-block" id="Template"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.Template">[docs]</a><span class="k">class</span> <span class="nc">Template</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template_string</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">engine</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">template_string</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">template_string</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">TemplateEncodingError</span><span class="p">(</span><span class="s2">&quot;Templates can only be constructed &quot;</span>
                                        <span class="s2">&quot;from unicode or UTF-8 strings.&quot;</span><span class="p">)</span>
        <span class="c1"># If Template is instantiated directly rather than from an Engine and</span>
        <span class="c1"># exactly one Django template engine is configured, use that engine.</span>
        <span class="c1"># This is required to preserve backwards-compatibility for direct use</span>
        <span class="c1"># e.g. Template(&#39;...&#39;).render(Context({...}))</span>
        <span class="k">if</span> <span class="n">engine</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="kn">from</span> <span class="nn">.engine</span> <span class="k">import</span> <span class="n">Engine</span>
            <span class="n">engine</span> <span class="o">=</span> <span class="n">Engine</span><span class="o">.</span><span class="n">get_default</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">origin</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">origin</span> <span class="o">=</span> <span class="n">Origin</span><span class="p">(</span><span class="n">UNKNOWN_SOURCE</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">origin</span> <span class="o">=</span> <span class="n">origin</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">engine</span> <span class="o">=</span> <span class="n">engine</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">source</span> <span class="o">=</span> <span class="n">template_string</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nodelist</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">compile_nodelist</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodelist</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">subnode</span> <span class="ow">in</span> <span class="n">node</span><span class="p">:</span>
                <span class="k">yield</span> <span class="n">subnode</span>

    <span class="k">def</span> <span class="nf">_render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodelist</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>

<div class="viewcode-block" id="Template.render"><a class="viewcode-back" href="../../../ref/templates/api.html#django.template.Template.render">[docs]</a>    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="s2">&quot;Display stage -- can be called many times&quot;</span>
        <span class="k">with</span> <span class="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="o">.</span><span class="n">push_state</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
                <span class="k">with</span> <span class="n">context</span><span class="o">.</span><span class="n">bind_template</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
                    <span class="n">context</span><span class="o">.</span><span class="n">template_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
                    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span></div>

    <span class="k">def</span> <span class="nf">compile_nodelist</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Parse and compile the template source into a nodelist. If debug</span>
<span class="sd">        is True and an exception occurs during parsing, the exception is</span>
<span class="sd">        is annotated with contextual line information where it occurred in the</span>
<span class="sd">        template source.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
            <span class="n">lexer</span> <span class="o">=</span> <span class="n">DebugLexer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">lexer</span> <span class="o">=</span> <span class="n">Lexer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)</span>

        <span class="n">tokens</span> <span class="o">=</span> <span class="n">lexer</span><span class="o">.</span><span class="n">tokenize</span><span class="p">()</span>
        <span class="n">parser</span> <span class="o">=</span> <span class="n">Parser</span><span class="p">(</span>
            <span class="n">tokens</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">template_libraries</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">template_builtins</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">origin</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">()</span>
        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
                <span class="n">e</span><span class="o">.</span><span class="n">template_debug</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_exception_info</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">token</span><span class="p">)</span>
            <span class="k">raise</span>

    <span class="k">def</span> <span class="nf">get_exception_info</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a dictionary containing contextual line information of where</span>
<span class="sd">        the exception occurred in the template. The following information is</span>
<span class="sd">        provided:</span>

<span class="sd">        message</span>
<span class="sd">            The message of the exception raised.</span>

<span class="sd">        source_lines</span>
<span class="sd">            The lines before, after, and including the line the exception</span>
<span class="sd">            occurred on.</span>

<span class="sd">        line</span>
<span class="sd">            The line number the exception occurred on.</span>

<span class="sd">        before, during, after</span>
<span class="sd">            The line the exception occurred on split into three parts:</span>
<span class="sd">            1. The content before the token that raised the error.</span>
<span class="sd">            2. The token that raised the error.</span>
<span class="sd">            3. The content after the token that raised the error.</span>

<span class="sd">        total</span>
<span class="sd">            The number of lines in source_lines.</span>

<span class="sd">        top</span>
<span class="sd">            The line number where source_lines starts.</span>

<span class="sd">        bottom</span>
<span class="sd">            The line number where source_lines ends.</span>

<span class="sd">        start</span>
<span class="sd">            The start position of the token in the template source.</span>

<span class="sd">        end</span>
<span class="sd">            The end position of the token in the template source.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">position</span>
        <span class="n">context_lines</span> <span class="o">=</span> <span class="mi">10</span>
        <span class="n">line</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">upto</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">source_lines</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">before</span> <span class="o">=</span> <span class="n">during</span> <span class="o">=</span> <span class="n">after</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
        <span class="k">for</span> <span class="n">num</span><span class="p">,</span> <span class="nb">next</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">linebreak_iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)):</span>
            <span class="k">if</span> <span class="n">start</span> <span class="o">&gt;=</span> <span class="n">upto</span> <span class="ow">and</span> <span class="n">end</span> <span class="o">&lt;=</span> <span class="nb">next</span><span class="p">:</span>
                <span class="n">line</span> <span class="o">=</span> <span class="n">num</span>
                <span class="n">before</span> <span class="o">=</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="n">start</span><span class="p">])</span>
                <span class="n">during</span> <span class="o">=</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">end</span><span class="p">])</span>
                <span class="n">after</span> <span class="o">=</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">end</span><span class="p">:</span><span class="nb">next</span><span class="p">])</span>
            <span class="n">source_lines</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">num</span><span class="p">,</span> <span class="n">escape</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="nb">next</span><span class="p">])))</span>
            <span class="n">upto</span> <span class="o">=</span> <span class="nb">next</span>
        <span class="n">total</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">source_lines</span><span class="p">)</span>

        <span class="n">top</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">line</span> <span class="o">-</span> <span class="n">context_lines</span><span class="p">)</span>
        <span class="n">bottom</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">line</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">context_lines</span><span class="p">)</span>

        <span class="c1"># In some rare cases exc_value.args can be empty or an invalid</span>
        <span class="c1"># unicode string.</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">message</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">exception</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="k">except</span> <span class="p">(</span><span class="ne">IndexError</span><span class="p">,</span> <span class="ne">UnicodeDecodeError</span><span class="p">):</span>
            <span class="n">message</span> <span class="o">=</span> <span class="s1">&#39;(Could not get exception message)&#39;</span>

        <span class="k">return</span> <span class="p">{</span>
            <span class="s1">&#39;message&#39;</span><span class="p">:</span> <span class="n">message</span><span class="p">,</span>
            <span class="s1">&#39;source_lines&#39;</span><span class="p">:</span> <span class="n">source_lines</span><span class="p">[</span><span class="n">top</span><span class="p">:</span><span class="n">bottom</span><span class="p">],</span>
            <span class="s1">&#39;before&#39;</span><span class="p">:</span> <span class="n">before</span><span class="p">,</span>
            <span class="s1">&#39;during&#39;</span><span class="p">:</span> <span class="n">during</span><span class="p">,</span>
            <span class="s1">&#39;after&#39;</span><span class="p">:</span> <span class="n">after</span><span class="p">,</span>
            <span class="s1">&#39;top&#39;</span><span class="p">:</span> <span class="n">top</span><span class="p">,</span>
            <span class="s1">&#39;bottom&#39;</span><span class="p">:</span> <span class="n">bottom</span><span class="p">,</span>
            <span class="s1">&#39;total&#39;</span><span class="p">:</span> <span class="n">total</span><span class="p">,</span>
            <span class="s1">&#39;line&#39;</span><span class="p">:</span> <span class="n">line</span><span class="p">,</span>
            <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
            <span class="s1">&#39;start&#39;</span><span class="p">:</span> <span class="n">start</span><span class="p">,</span>
            <span class="s1">&#39;end&#39;</span><span class="p">:</span> <span class="n">end</span><span class="p">,</span>
        <span class="p">}</span></div>


<span class="k">def</span> <span class="nf">linebreak_iter</span><span class="p">(</span><span class="n">template_source</span><span class="p">):</span>
    <span class="k">yield</span> <span class="mi">0</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">template_source</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
    <span class="k">while</span> <span class="n">p</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">yield</span> <span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">template_source</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">yield</span> <span class="nb">len</span><span class="p">(</span><span class="n">template_source</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>


<span class="k">class</span> <span class="nc">Token</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token_type</span><span class="p">,</span> <span class="n">contents</span><span class="p">,</span> <span class="n">position</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">lineno</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        A token representing a string from the template.</span>

<span class="sd">        token_type</span>
<span class="sd">            One of TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK, or TOKEN_COMMENT.</span>

<span class="sd">        contents</span>
<span class="sd">            The token source string.</span>

<span class="sd">        position</span>
<span class="sd">            An optional tuple containing the start and end index of the token</span>
<span class="sd">            in the template source. This is used for traceback information</span>
<span class="sd">            when debug is on.</span>

<span class="sd">        lineno</span>
<span class="sd">            The line number the token appears on in the template source.</span>
<span class="sd">            This is used for traceback information and gettext files.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">token_type</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span> <span class="o">=</span> <span class="n">token_type</span><span class="p">,</span> <span class="n">contents</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">lineno</span> <span class="o">=</span> <span class="n">lineno</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">position</span> <span class="o">=</span> <span class="n">position</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">token_name</span> <span class="o">=</span> <span class="n">TOKEN_MAPPING</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">token_type</span><span class="p">]</span>
        <span class="k">return</span> <span class="p">(</span><span class="s1">&#39;&lt;</span><span class="si">%s</span><span class="s1"> token: &quot;</span><span class="si">%s</span><span class="s1">...&quot;&gt;&#39;</span> <span class="o">%</span>
                <span class="p">(</span><span class="n">token_name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[:</span><span class="mi">20</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)))</span>

    <span class="k">def</span> <span class="nf">split_contents</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">split</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">bits</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">smart_split</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">))</span>
        <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">bits</span><span class="p">:</span>
            <span class="c1"># Handle translation-marked template pieces</span>
            <span class="k">if</span> <span class="n">bit</span><span class="o">.</span><span class="n">startswith</span><span class="p">((</span><span class="s1">&#39;_(&quot;&#39;</span><span class="p">,</span> <span class="s2">&quot;_(&#39;&quot;</span><span class="p">)):</span>
                <span class="n">sentinel</span> <span class="o">=</span> <span class="n">bit</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="s1">&#39;)&#39;</span>
                <span class="n">trans_bit</span> <span class="o">=</span> <span class="p">[</span><span class="n">bit</span><span class="p">]</span>
                <span class="k">while</span> <span class="ow">not</span> <span class="n">bit</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="n">sentinel</span><span class="p">):</span>
                    <span class="n">bit</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span>
                    <span class="n">trans_bit</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bit</span><span class="p">)</span>
                <span class="n">bit</span> <span class="o">=</span> <span class="s1">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">trans_bit</span><span class="p">)</span>
            <span class="n">split</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bit</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">split</span>


<span class="k">class</span> <span class="nc">Lexer</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template_string</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span> <span class="o">=</span> <span class="n">template_string</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="o">=</span> <span class="kc">False</span>

    <span class="k">def</span> <span class="nf">tokenize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a list of tokens from a given template_string.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">in_tag</span> <span class="o">=</span> <span class="kc">False</span>
        <span class="n">lineno</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">tag_re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">bit</span><span class="p">:</span>
                <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">bit</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="p">))</span>
            <span class="n">in_tag</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_tag</span>
            <span class="n">lineno</span> <span class="o">+=</span> <span class="n">bit</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">result</span>

    <span class="k">def</span> <span class="nf">create_token</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token_string</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Convert the given token string into a new Token object and return it.</span>
<span class="sd">        If in_tag is True, we are processing something that matched a tag,</span>
<span class="sd">        otherwise it should be treated as a literal string.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">in_tag</span> <span class="ow">and</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">BLOCK_TAG_START</span><span class="p">):</span>
            <span class="c1"># The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.</span>
            <span class="c1"># We could do len(BLOCK_TAG_START) to be more &quot;correct&quot;, but we&#39;ve</span>
            <span class="c1"># hard-coded the 2s here for performance. And it&#39;s not like</span>
            <span class="c1"># the TAG_START values are going to change anytime, anyway.</span>
            <span class="n">block_content</span> <span class="o">=</span> <span class="n">token_string</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="ow">and</span> <span class="n">block_content</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="o">=</span> <span class="kc">False</span>
        <span class="k">if</span> <span class="n">in_tag</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">VARIABLE_TAG_START</span><span class="p">):</span>
                <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_VAR</span><span class="p">,</span> <span class="n">token_string</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">BLOCK_TAG_START</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">block_content</span><span class="p">[:</span><span class="mi">9</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;verbatim&#39;</span><span class="p">,</span> <span class="s1">&#39;verbatim &#39;</span><span class="p">):</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">verbatim</span> <span class="o">=</span> <span class="s1">&#39;end</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">block_content</span>
                <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_BLOCK</span><span class="p">,</span> <span class="n">block_content</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">token_string</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">COMMENT_TAG_START</span><span class="p">):</span>
                <span class="n">content</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
                <span class="k">if</span> <span class="n">token_string</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">TRANSLATOR_COMMENT_MARK</span><span class="p">):</span>
                    <span class="n">content</span> <span class="o">=</span> <span class="n">token_string</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
                <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_COMMENT</span><span class="p">,</span> <span class="n">content</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="p">(</span><span class="n">TOKEN_TEXT</span><span class="p">,</span> <span class="n">token_string</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">lineno</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">token</span>


<span class="k">class</span> <span class="nc">DebugLexer</span><span class="p">(</span><span class="n">Lexer</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">tokenize</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Split a template string into tokens and annotates each token with its</span>
<span class="sd">        start and end position in the source. This is slower than the default</span>
<span class="sd">        lexer so we only use it when debug is True.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">lineno</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">upto</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">tag_re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">):</span>
            <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">span</span><span class="p">()</span>
            <span class="k">if</span> <span class="n">start</span> <span class="o">&gt;</span> <span class="n">upto</span><span class="p">:</span>
                <span class="n">token_string</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="n">start</span><span class="p">]</span>
                <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">token_string</span><span class="p">,</span> <span class="p">(</span><span class="n">upto</span><span class="p">,</span> <span class="n">start</span><span class="p">),</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
                <span class="n">lineno</span> <span class="o">+=</span> <span class="n">token_string</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
                <span class="n">upto</span> <span class="o">=</span> <span class="n">start</span>
            <span class="n">token_string</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">end</span><span class="p">]</span>
            <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">token_string</span><span class="p">,</span> <span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">),</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
            <span class="n">lineno</span> <span class="o">+=</span> <span class="n">token_string</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
            <span class="n">upto</span> <span class="o">=</span> <span class="n">end</span>
        <span class="n">last_bit</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">template_string</span><span class="p">[</span><span class="n">upto</span><span class="p">:]</span>
        <span class="k">if</span> <span class="n">last_bit</span><span class="p">:</span>
            <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">create_token</span><span class="p">(</span><span class="n">last_bit</span><span class="p">,</span> <span class="p">(</span><span class="n">upto</span><span class="p">,</span> <span class="n">upto</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">last_bit</span><span class="p">)),</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">in_tag</span><span class="o">=</span><span class="kc">False</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">result</span>


<span class="k">class</span> <span class="nc">Parser</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tokens</span><span class="p">,</span> <span class="n">libraries</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">builtins</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">=</span> <span class="n">tokens</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tags</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">filters</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">if</span> <span class="n">libraries</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">libraries</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">if</span> <span class="n">builtins</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">builtins</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">libraries</span> <span class="o">=</span> <span class="n">libraries</span>
        <span class="k">for</span> <span class="n">builtin</span> <span class="ow">in</span> <span class="n">builtins</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">add_library</span><span class="p">(</span><span class="n">builtin</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">origin</span> <span class="o">=</span> <span class="n">origin</span>

    <span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parse_until</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Iterate through the parser tokens and compiles each one into a node.</span>

<span class="sd">        If parse_until is provided, parsing will stop once one of the</span>
<span class="sd">        specified tokens has been reached. This is formatted as a list of</span>
<span class="sd">        tokens, e.g. [&#39;elif&#39;, &#39;else&#39;, &#39;endif&#39;]. If no matching token is</span>
<span class="sd">        reached, raise an exception with the unclosed block tag details.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">parse_until</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">parse_until</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">nodelist</span> <span class="o">=</span> <span class="n">NodeList</span><span class="p">()</span>
        <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">:</span>
            <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">next_token</span><span class="p">()</span>
            <span class="c1"># Use the raw values here for TOKEN_* for a tiny performance boost.</span>
            <span class="k">if</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>  <span class="c1"># TOKEN_TEXT</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">extend_nodelist</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">TextNode</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="p">),</span> <span class="n">token</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>  <span class="c1"># TOKEN_VAR</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="s1">&#39;Empty variable tag on line </span><span class="si">%d</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">)</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">filter_expression</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">compile_filter</span><span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="p">)</span>
                <span class="k">except</span> <span class="n">TemplateSyntaxError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
                <span class="n">var_node</span> <span class="o">=</span> <span class="n">VariableNode</span><span class="p">(</span><span class="n">filter_expression</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">extend_nodelist</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">var_node</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>  <span class="c1"># TOKEN_BLOCK</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">command</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
                <span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="s1">&#39;Empty block tag on line </span><span class="si">%d</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">parse_until</span><span class="p">:</span>
                    <span class="c1"># A matching token has been reached. Return control to</span>
                    <span class="c1"># the caller. Put the token back on the token list so the</span>
                    <span class="c1"># caller knows where it terminated.</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">prepend_token</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>
                    <span class="k">return</span> <span class="n">nodelist</span>
                <span class="c1"># Add the token to the command stack. This is used for error</span>
                <span class="c1"># messages if further parsing fails due to an unclosed block</span>
                <span class="c1"># tag.</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">command</span><span class="p">,</span> <span class="n">token</span><span class="p">))</span>
                <span class="c1"># Get the tag callback function from the ones registered with</span>
                <span class="c1"># the parser.</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">compile_func</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="p">[</span><span class="n">command</span><span class="p">]</span>
                <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">invalid_block_tag</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="n">parse_until</span><span class="p">)</span>
                <span class="c1"># Compile the callback into a node object and add it to</span>
                <span class="c1"># the node list.</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">compiled_result</span> <span class="o">=</span> <span class="n">compile_func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span>
                <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">extend_nodelist</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">compiled_result</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span>
                <span class="c1"># Compile success. Remove the token from the command stack.</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">parse_until</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">unclosed_block_tag</span><span class="p">(</span><span class="n">parse_until</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">nodelist</span>

    <span class="k">def</span> <span class="nf">skip_past</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endtag</span><span class="p">):</span>
        <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">:</span>
            <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">next_token</span><span class="p">()</span>
            <span class="k">if</span> <span class="n">token</span><span class="o">.</span><span class="n">token_type</span> <span class="o">==</span> <span class="n">TOKEN_BLOCK</span> <span class="ow">and</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span> <span class="o">==</span> <span class="n">endtag</span><span class="p">:</span>
                <span class="k">return</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">unclosed_block_tag</span><span class="p">([</span><span class="n">endtag</span><span class="p">])</span>

    <span class="k">def</span> <span class="nf">extend_nodelist</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodelist</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
        <span class="c1"># Check that non-text nodes don&#39;t appear before an extends tag.</span>
        <span class="k">if</span> <span class="n">node</span><span class="o">.</span><span class="n">must_be_first</span> <span class="ow">and</span> <span class="n">nodelist</span><span class="o">.</span><span class="n">contains_nontext</span><span class="p">:</span>
            <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
                <span class="n">token</span><span class="p">,</span> <span class="s1">&#39;</span><span class="si">%r</span><span class="s1"> must be the first tag in the template.&#39;</span> <span class="o">%</span> <span class="n">node</span><span class="p">,</span>
            <span class="p">)</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">nodelist</span><span class="p">,</span> <span class="n">NodeList</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">TextNode</span><span class="p">):</span>
            <span class="n">nodelist</span><span class="o">.</span><span class="n">contains_nontext</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="c1"># Set origin and token here since we can&#39;t modify the node __init__()</span>
        <span class="c1"># method.</span>
        <span class="n">node</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">token</span>
        <span class="n">node</span><span class="o">.</span><span class="n">origin</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span>
        <span class="n">nodelist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return an exception annotated with the originating token. Since the</span>
<span class="sd">        parser can be called recursively, check if a token is already set. This</span>
<span class="sd">        ensures the innermost token is highlighted if an exception occurs,</span>
<span class="sd">        e.g. a compile error within the body of an if statement.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="ne">Exception</span><span class="p">):</span>
            <span class="n">e</span> <span class="o">=</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">&#39;token&#39;</span><span class="p">):</span>
            <span class="n">e</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">token</span>
        <span class="k">return</span> <span class="n">e</span>

    <span class="k">def</span> <span class="nf">invalid_block_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">,</span> <span class="n">command</span><span class="p">,</span> <span class="n">parse_until</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">parse_until</span><span class="p">:</span>
            <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
                <span class="n">token</span><span class="p">,</span>
                <span class="s2">&quot;Invalid block tag on line </span><span class="si">%d</span><span class="s2">: &#39;</span><span class="si">%s</span><span class="s2">&#39;, expected </span><span class="si">%s</span><span class="s2">. Did you &quot;</span>
                <span class="s2">&quot;forget to register or load this tag?&quot;</span> <span class="o">%</span> <span class="p">(</span>
                    <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">,</span>
                    <span class="n">command</span><span class="p">,</span>
                    <span class="n">get_text_list</span><span class="p">([</span><span class="s2">&quot;&#39;</span><span class="si">%s</span><span class="s2">&#39;&quot;</span> <span class="o">%</span> <span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">parse_until</span><span class="p">],</span> <span class="s1">&#39;or&#39;</span><span class="p">),</span>
                <span class="p">),</span>
            <span class="p">)</span>
        <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
            <span class="n">token</span><span class="p">,</span>
            <span class="s2">&quot;Invalid block tag on line </span><span class="si">%d</span><span class="s2">: &#39;</span><span class="si">%s</span><span class="s2">&#39;. Did you forget to register &quot;</span>
            <span class="s2">&quot;or load this tag?&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">,</span> <span class="n">command</span><span class="p">)</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="nf">unclosed_block_tag</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parse_until</span><span class="p">):</span>
        <span class="n">command</span><span class="p">,</span> <span class="n">token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">command_stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">msg</span> <span class="o">=</span> <span class="s2">&quot;Unclosed tag on line </span><span class="si">%d</span><span class="s2">: &#39;</span><span class="si">%s</span><span class="s2">&#39;. Looking for one of: </span><span class="si">%s</span><span class="s2">.&quot;</span> <span class="o">%</span> <span class="p">(</span>
            <span class="n">token</span><span class="o">.</span><span class="n">lineno</span><span class="p">,</span>
            <span class="n">command</span><span class="p">,</span>
            <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">parse_until</span><span class="p">),</span>
        <span class="p">)</span>
        <span class="k">raise</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">next_token</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">prepend_token</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">token</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">delete_first_token</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

    <span class="k">def</span> <span class="nf">add_library</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lib</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">lib</span><span class="o">.</span><span class="n">tags</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">lib</span><span class="o">.</span><span class="n">filters</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">compile_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Convenient wrapper for FilterExpression</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">FilterExpression</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">find_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filter_name</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">filter_name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">[</span><span class="n">filter_name</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">&quot;Invalid filter: &#39;</span><span class="si">%s</span><span class="s2">&#39;&quot;</span> <span class="o">%</span> <span class="n">filter_name</span><span class="p">)</span>


<span class="c1"># This only matches constant *strings* (things in quotes or marked for</span>
<span class="c1"># translation). Numbers are treated as variables for implementation reasons</span>
<span class="c1"># (so that they retain their type when passed to filters).</span>
<span class="n">constant_string</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;&quot;&quot;</span>
<span class="s2">(?:</span><span class="si">%(i18n_open)s%(strdq)s%(i18n_close)s</span><span class="s2">|</span>
<span class="si">%(i18n_open)s%(strsq)s%(i18n_close)s</span><span class="s2">|</span>
<span class="si">%(strdq)s</span><span class="s2">|</span>
<span class="si">%(strsq)s</span><span class="s2">)</span>
<span class="s2">&quot;&quot;&quot;</span> <span class="o">%</span> <span class="p">{</span>
    <span class="s1">&#39;strdq&#39;</span><span class="p">:</span> <span class="sa">r</span><span class="s1">&#39;&quot;[^&quot;</span><span class="se">\\</span><span class="s1">]*(?:</span><span class="se">\\</span><span class="s1">.[^&quot;</span><span class="se">\\</span><span class="s1">]*)*&quot;&#39;</span><span class="p">,</span>  <span class="c1"># double-quoted string</span>
    <span class="s1">&#39;strsq&#39;</span><span class="p">:</span> <span class="sa">r</span><span class="s2">&quot;&#39;[^&#39;</span><span class="se">\\</span><span class="s2">]*(?:</span><span class="se">\\</span><span class="s2">.[^&#39;</span><span class="se">\\</span><span class="s2">]*)*&#39;&quot;</span><span class="p">,</span>  <span class="c1"># single-quoted string</span>
    <span class="s1">&#39;i18n_open&#39;</span><span class="p">:</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="s2">&quot;_(&quot;</span><span class="p">),</span>
    <span class="s1">&#39;i18n_close&#39;</span><span class="p">:</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="s2">&quot;)&quot;</span><span class="p">),</span>
<span class="p">}</span>
<span class="n">constant_string</span> <span class="o">=</span> <span class="n">constant_string</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span>

<span class="n">filter_raw_string</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;&quot;&quot;</span>
<span class="s2">^(?P&lt;constant&gt;</span><span class="si">%(constant)s</span><span class="s2">)|</span>
<span class="s2">^(?P&lt;var&gt;[</span><span class="si">%(var_chars)s</span><span class="s2">]+|</span><span class="si">%(num)s</span><span class="s2">)|</span>
<span class="s2"> (?:\s*</span><span class="si">%(filter_sep)s</span><span class="s2">\s*</span>
<span class="s2">     (?P&lt;filter_name&gt;\w+)</span>
<span class="s2">         (?:</span><span class="si">%(arg_sep)s</span><span class="s2"></span>
<span class="s2">             (?:</span>
<span class="s2">              (?P&lt;constant_arg&gt;</span><span class="si">%(constant)s</span><span class="s2">)|</span>
<span class="s2">              (?P&lt;var_arg&gt;[</span><span class="si">%(var_chars)s</span><span class="s2">]+|</span><span class="si">%(num)s</span><span class="s2">)</span>
<span class="s2">             )</span>
<span class="s2">         )?</span>
<span class="s2"> )&quot;&quot;&quot;</span> <span class="o">%</span> <span class="p">{</span>
    <span class="s1">&#39;constant&#39;</span><span class="p">:</span> <span class="n">constant_string</span><span class="p">,</span>
    <span class="s1">&#39;num&#39;</span><span class="p">:</span> <span class="sa">r</span><span class="s1">&#39;[-+\.]?\d[\d\.e]*&#39;</span><span class="p">,</span>
    <span class="s1">&#39;var_chars&#39;</span><span class="p">:</span> <span class="sa">r</span><span class="s1">&#39;\w\.&#39;</span><span class="p">,</span>
    <span class="s1">&#39;filter_sep&#39;</span><span class="p">:</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">FILTER_SEPARATOR</span><span class="p">),</span>
    <span class="s1">&#39;arg_sep&#39;</span><span class="p">:</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">FILTER_ARGUMENT_SEPARATOR</span><span class="p">),</span>
<span class="p">}</span>

<span class="n">filter_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">filter_raw_string</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">UNICODE</span> <span class="o">|</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">FilterExpression</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Parses a variable token and its optional filters (all as a single string),</span>
<span class="sd">    and return a list of tuples of the filter name and arguments.</span>
<span class="sd">    Sample::</span>

<span class="sd">        &gt;&gt;&gt; token = &#39;variable|default:&quot;Default value&quot;|date:&quot;Y-m-d&quot;&#39;</span>
<span class="sd">        &gt;&gt;&gt; p = Parser(&#39;&#39;)</span>
<span class="sd">        &gt;&gt;&gt; fe = FilterExpression(token, p)</span>
<span class="sd">        &gt;&gt;&gt; len(fe.filters)</span>
<span class="sd">        2</span>
<span class="sd">        &gt;&gt;&gt; fe.var</span>
<span class="sd">        &lt;Variable: &#39;variable&#39;&gt;</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">,</span> <span class="n">parser</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">token</span>
        <span class="n">matches</span> <span class="o">=</span> <span class="n">filter_re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>
        <span class="n">var_obj</span> <span class="o">=</span> <span class="kc">None</span>
        <span class="n">filters</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">upto</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">matches</span><span class="p">:</span>
            <span class="n">start</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
            <span class="k">if</span> <span class="n">upto</span> <span class="o">!=</span> <span class="n">start</span><span class="p">:</span>
                <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">&quot;Could not parse some characters: &quot;</span>
                                          <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">|</span><span class="si">%s</span><span class="s2">|</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span>
                                          <span class="p">(</span><span class="n">token</span><span class="p">[:</span><span class="n">upto</span><span class="p">],</span> <span class="n">token</span><span class="p">[</span><span class="n">upto</span><span class="p">:</span><span class="n">start</span><span class="p">],</span>
                                           <span class="n">token</span><span class="p">[</span><span class="n">start</span><span class="p">:]))</span>
            <span class="k">if</span> <span class="n">var_obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
                <span class="n">var</span><span class="p">,</span> <span class="n">constant</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">&quot;var&quot;</span><span class="p">,</span> <span class="s2">&quot;constant&quot;</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">constant</span><span class="p">:</span>
                    <span class="k">try</span><span class="p">:</span>
                        <span class="n">var_obj</span> <span class="o">=</span> <span class="n">Variable</span><span class="p">(</span><span class="n">constant</span><span class="p">)</span><span class="o">.</span><span class="n">resolve</span><span class="p">({})</span>
                    <span class="k">except</span> <span class="n">VariableDoesNotExist</span><span class="p">:</span>
                        <span class="n">var_obj</span> <span class="o">=</span> <span class="kc">None</span>
                <span class="k">elif</span> <span class="n">var</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">&quot;Could not find variable at &quot;</span>
                                              <span class="s2">&quot;start of </span><span class="si">%s</span><span class="s2">.&quot;</span> <span class="o">%</span> <span class="n">token</span><span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">var_obj</span> <span class="o">=</span> <span class="n">Variable</span><span class="p">(</span><span class="n">var</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">filter_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">&quot;filter_name&quot;</span><span class="p">)</span>
                <span class="n">args</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="n">constant_arg</span><span class="p">,</span> <span class="n">var_arg</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">&quot;constant_arg&quot;</span><span class="p">,</span> <span class="s2">&quot;var_arg&quot;</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">constant_arg</span><span class="p">:</span>
                    <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="kc">False</span><span class="p">,</span> <span class="n">Variable</span><span class="p">(</span><span class="n">constant_arg</span><span class="p">)</span><span class="o">.</span><span class="n">resolve</span><span class="p">({})))</span>
                <span class="k">elif</span> <span class="n">var_arg</span><span class="p">:</span>
                    <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="kc">True</span><span class="p">,</span> <span class="n">Variable</span><span class="p">(</span><span class="n">var_arg</span><span class="p">)))</span>
                <span class="n">filter_func</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">find_filter</span><span class="p">(</span><span class="n">filter_name</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">args_check</span><span class="p">(</span><span class="n">filter_name</span><span class="p">,</span> <span class="n">filter_func</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
                <span class="n">filters</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">filter_func</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
            <span class="n">upto</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">upto</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">token</span><span class="p">):</span>
            <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">&quot;Could not parse the remainder: &#39;</span><span class="si">%s</span><span class="s2">&#39; &quot;</span>
                                      <span class="s2">&quot;from &#39;</span><span class="si">%s</span><span class="s2">&#39;&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">token</span><span class="p">[</span><span class="n">upto</span><span class="p">:],</span> <span class="n">token</span><span class="p">))</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">filters</span> <span class="o">=</span> <span class="n">filters</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">=</span> <span class="n">var_obj</span>

    <span class="k">def</span> <span class="nf">resolve</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">ignore_failures</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">,</span> <span class="n">Variable</span><span class="p">):</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
            <span class="k">except</span> <span class="n">VariableDoesNotExist</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">ignore_failures</span><span class="p">:</span>
                    <span class="n">obj</span> <span class="o">=</span> <span class="kc">None</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">string_if_invalid</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span>
                    <span class="k">if</span> <span class="n">string_if_invalid</span><span class="p">:</span>
                        <span class="k">if</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="ow">in</span> <span class="n">string_if_invalid</span><span class="p">:</span>
                            <span class="k">return</span> <span class="n">string_if_invalid</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span>
                        <span class="k">else</span><span class="p">:</span>
                            <span class="k">return</span> <span class="n">string_if_invalid</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">obj</span> <span class="o">=</span> <span class="n">string_if_invalid</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span>
        <span class="n">escape_isnt_last_filter</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">for</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">:</span>
            <span class="n">arg_vals</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="k">for</span> <span class="n">lookup</span><span class="p">,</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">lookup</span><span class="p">:</span>
                    <span class="n">arg_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">mark_safe</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">arg_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">arg</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">))</span>
            <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">&#39;expects_localtime&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span>
                <span class="n">obj</span> <span class="o">=</span> <span class="n">template_localtime</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">context</span><span class="o">.</span><span class="n">use_tz</span><span class="p">)</span>
            <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">&#39;needs_autoescape&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span>
                <span class="n">new_obj</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">autoescape</span><span class="o">=</span><span class="n">context</span><span class="o">.</span><span class="n">autoescape</span><span class="p">,</span> <span class="o">*</span><span class="n">arg_vals</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">new_obj</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">arg_vals</span><span class="p">)</span>
            <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">&#39;is_safe&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">SafeData</span><span class="p">):</span>
                <span class="n">obj</span> <span class="o">=</span> <span class="n">mark_safe</span><span class="p">(</span><span class="n">new_obj</span><span class="p">)</span>
            <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">EscapeData</span><span class="p">):</span>
                <span class="k">with</span> <span class="n">warnings</span><span class="o">.</span><span class="n">catch_warnings</span><span class="p">():</span>
                    <span class="c1"># Ignore mark_for_escaping deprecation as this will be</span>
                    <span class="c1"># removed in Django 2.0.</span>
                    <span class="n">warnings</span><span class="o">.</span><span class="n">simplefilter</span><span class="p">(</span><span class="s1">&#39;ignore&#39;</span><span class="p">,</span> <span class="n">category</span><span class="o">=</span><span class="n">RemovedInDjango20Warning</span><span class="p">)</span>
                    <span class="n">obj</span> <span class="o">=</span> <span class="n">mark_for_escaping</span><span class="p">(</span><span class="n">new_obj</span><span class="p">)</span>
                    <span class="n">escape_isnt_last_filter</span> <span class="o">=</span> <span class="kc">False</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">obj</span> <span class="o">=</span> <span class="n">new_obj</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">escape_isnt_last_filter</span><span class="p">:</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
                <span class="s2">&quot;escape isn&#39;t the last filter in </span><span class="si">%s</span><span class="s2"> and will be applied &quot;</span>
                <span class="s2">&quot;immediately in Django 2.0 so the output may change.&quot;</span>
                <span class="o">%</span> <span class="p">[</span><span class="n">func</span><span class="o">.</span><span class="vm">__name__</span> <span class="k">for</span> <span class="n">func</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">],</span>
                <span class="n">RemovedInDjango20Warning</span><span class="p">,</span> <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span>
            <span class="p">)</span>
        <span class="k">return</span> <span class="n">obj</span>

    <span class="k">def</span> <span class="nf">args_check</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">provided</span><span class="p">):</span>
        <span class="n">provided</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">provided</span><span class="p">)</span>
        <span class="c1"># First argument, filter input, is implied.</span>
        <span class="n">plen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">provided</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="c1"># Check to see if a decorator is providing the real function.</span>
        <span class="n">func</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">&#39;_decorated_function&#39;</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span>

        <span class="n">args</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">defaults</span> <span class="o">=</span> <span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
        <span class="n">alen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
        <span class="n">dlen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">defaults</span> <span class="ow">or</span> <span class="p">[])</span>
        <span class="c1"># Not enough OR Too many</span>
        <span class="k">if</span> <span class="n">plen</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">alen</span> <span class="o">-</span> <span class="n">dlen</span><span class="p">)</span> <span class="ow">or</span> <span class="n">plen</span> <span class="o">&gt;</span> <span class="n">alen</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> requires </span><span class="si">%d</span><span class="s2"> arguments, </span><span class="si">%d</span><span class="s2"> provided&quot;</span> <span class="o">%</span>
                                      <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">alen</span> <span class="o">-</span> <span class="n">dlen</span><span class="p">,</span> <span class="n">plen</span><span class="p">))</span>

        <span class="k">return</span> <span class="kc">True</span>
    <span class="n">args_check</span> <span class="o">=</span> <span class="nb">staticmethod</span><span class="p">(</span><span class="n">args_check</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span>


<span class="k">class</span> <span class="nc">Variable</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A template variable, resolvable against a given context. The variable may</span>
<span class="sd">    be a hard-coded string (if it begins and ends with single or double quote</span>
<span class="sd">    marks)::</span>

<span class="sd">        &gt;&gt;&gt; c = {&#39;article&#39;: {&#39;section&#39;:&#39;News&#39;}}</span>
<span class="sd">        &gt;&gt;&gt; Variable(&#39;article.section&#39;).resolve(c)</span>
<span class="sd">        &#39;News&#39;</span>
<span class="sd">        &gt;&gt;&gt; Variable(&#39;article&#39;).resolve(c)</span>
<span class="sd">        {&#39;section&#39;: &#39;News&#39;}</span>
<span class="sd">        &gt;&gt;&gt; class AClass: pass</span>
<span class="sd">        &gt;&gt;&gt; c = AClass()</span>
<span class="sd">        &gt;&gt;&gt; c.article = AClass()</span>
<span class="sd">        &gt;&gt;&gt; c.article.section = &#39;News&#39;</span>

<span class="sd">    (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is &#39;.&#39;)</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">var</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">=</span> <span class="n">var</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="kc">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span> <span class="o">=</span> <span class="kc">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">translate</span> <span class="o">=</span> <span class="kc">False</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">message_context</span> <span class="o">=</span> <span class="kc">None</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">var</span><span class="p">,</span> <span class="n">six</span><span class="o">.</span><span class="n">string_types</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
                <span class="s2">&quot;Variable must be a string or number, got </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="nb">type</span><span class="p">(</span><span class="n">var</span><span class="p">))</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="c1"># First try to treat this variable as a number.</span>
            <span class="c1">#</span>
            <span class="c1"># Note that this could cause an OverflowError here that we&#39;re not</span>
            <span class="c1"># catching. Since this should only happen at compile time, that&#39;s</span>
            <span class="c1"># probably OK.</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">var</span><span class="p">)</span>

            <span class="c1"># So it&#39;s a float... is it an int? If the original value contained a</span>
            <span class="c1"># dot or an &quot;e&quot; then it was a float, not an int.</span>
            <span class="k">if</span> <span class="s1">&#39;.&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">var</span> <span class="ow">and</span> <span class="s1">&#39;e&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">var</span><span class="o">.</span><span class="n">lower</span><span class="p">():</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">literal</span><span class="p">)</span>

            <span class="c1"># &quot;2.&quot; is invalid</span>
            <span class="k">if</span> <span class="n">var</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">):</span>
                <span class="k">raise</span> <span class="ne">ValueError</span>

        <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
            <span class="c1"># A ValueError means that the variable isn&#39;t a number.</span>
            <span class="k">if</span> <span class="n">var</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;_(&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">var</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;)&#39;</span><span class="p">):</span>
                <span class="c1"># The result of the lookup should be translated at rendering</span>
                <span class="c1"># time.</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">translate</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="n">var</span> <span class="o">=</span> <span class="n">var</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
            <span class="c1"># If it&#39;s wrapped with quotes (single or double), then</span>
            <span class="c1"># we&#39;re also dealing with a literal.</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">literal</span> <span class="o">=</span> <span class="n">mark_safe</span><span class="p">(</span><span class="n">unescape_string_literal</span><span class="p">(</span><span class="n">var</span><span class="p">))</span>
            <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
                <span class="c1"># Otherwise we&#39;ll set self.lookups so that resolve() knows we&#39;re</span>
                <span class="c1"># dealing with a bonafide variable</span>
                <span class="k">if</span> <span class="n">var</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">VARIABLE_ATTRIBUTE_SEPARATOR</span> <span class="o">+</span> <span class="s1">&#39;_&#39;</span><span class="p">)</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="n">var</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;_&#39;</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="n">TemplateSyntaxError</span><span class="p">(</span><span class="s2">&quot;Variables and attributes may &quot;</span>
                                              <span class="s2">&quot;not begin with underscores: &#39;</span><span class="si">%s</span><span class="s2">&#39;&quot;</span> <span class="o">%</span>
                                              <span class="n">var</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">var</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">VARIABLE_ATTRIBUTE_SEPARATOR</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">resolve</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Resolve this variable against a given context.&quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="c1"># We&#39;re dealing with a variable that needs to be resolved</span>
            <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve_lookup</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c1"># We&#39;re dealing with a literal, so it&#39;s already been &quot;resolved&quot;</span>
            <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">literal</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">translate</span><span class="p">:</span>
            <span class="n">is_safe</span> <span class="o">=</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">SafeData</span><span class="p">)</span>
            <span class="n">msgid</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;%&#39;</span><span class="p">,</span> <span class="s1">&#39;</span><span class="si">%%</span><span class="s1">&#39;</span><span class="p">)</span>
            <span class="n">msgid</span> <span class="o">=</span> <span class="n">mark_safe</span><span class="p">(</span><span class="n">msgid</span><span class="p">)</span> <span class="k">if</span> <span class="n">is_safe</span> <span class="k">else</span> <span class="n">msgid</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">message_context</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">pgettext_lazy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">message_context</span><span class="p">,</span> <span class="n">msgid</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">ugettext_lazy</span><span class="p">(</span><span class="n">msgid</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">value</span>

    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;&lt;</span><span class="si">%s</span><span class="s2">: </span><span class="si">%r</span><span class="s2">&gt;&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">var</span>

    <span class="k">def</span> <span class="nf">_resolve_lookup</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Performs resolution of a real variable (i.e. not a literal) against the</span>
<span class="sd">        given context.</span>

<span class="sd">        As indicated by the method&#39;s name, this method is an implementation</span>
<span class="sd">        detail and shouldn&#39;t be called by external code. Use Variable.resolve()</span>
<span class="sd">        instead.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">current</span> <span class="o">=</span> <span class="n">context</span>
        <span class="k">try</span><span class="p">:</span>  <span class="c1"># catch-all for silent variable failures</span>
            <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookups</span><span class="p">:</span>
                <span class="k">try</span><span class="p">:</span>  <span class="c1"># dictionary lookup</span>
                    <span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="p">[</span><span class="n">bit</span><span class="p">]</span>
                    <span class="c1"># ValueError/IndexError are for numpy.array lookup on</span>
                    <span class="c1"># numpy &lt; 1.9 and 1.9+ respectively</span>
                <span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">,</span> <span class="ne">KeyError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span>
                    <span class="k">try</span><span class="p">:</span>  <span class="c1"># attribute lookup</span>
                        <span class="c1"># Don&#39;t return class attributes if the class is the context:</span>
                        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">BaseContext</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">getattr</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">current</span><span class="p">),</span> <span class="n">bit</span><span class="p">):</span>
                            <span class="k">raise</span> <span class="ne">AttributeError</span>
                        <span class="n">current</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">bit</span><span class="p">)</span>
                    <span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">):</span>
                        <span class="c1"># Reraise if the exception was raised by a @property</span>
                        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="n">BaseContext</span><span class="p">)</span> <span class="ow">and</span> <span class="n">bit</span> <span class="ow">in</span> <span class="nb">dir</span><span class="p">(</span><span class="n">current</span><span class="p">):</span>
                            <span class="k">raise</span>
                        <span class="k">try</span><span class="p">:</span>  <span class="c1"># list-index lookup</span>
                            <span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">bit</span><span class="p">)]</span>
                        <span class="k">except</span> <span class="p">(</span><span class="ne">IndexError</span><span class="p">,</span>  <span class="c1"># list index out of range</span>
                                <span class="ne">ValueError</span><span class="p">,</span>  <span class="c1"># invalid literal for int()</span>
                                <span class="ne">KeyError</span><span class="p">,</span>    <span class="c1"># current is a dict without `int(bit)` key</span>
                                <span class="ne">TypeError</span><span class="p">):</span>  <span class="c1"># unsubscriptable object</span>
                            <span class="k">raise</span> <span class="n">VariableDoesNotExist</span><span class="p">(</span><span class="s2">&quot;Failed lookup for key &quot;</span>
                                                       <span class="s2">&quot;[</span><span class="si">%s</span><span class="s2">] in </span><span class="si">%r</span><span class="s2">&quot;</span><span class="p">,</span>
                                                       <span class="p">(</span><span class="n">bit</span><span class="p">,</span> <span class="n">current</span><span class="p">))</span>  <span class="c1"># missing attribute</span>
                <span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">current</span><span class="p">):</span>
                    <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="s1">&#39;do_not_call_in_templates&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span>
                        <span class="k">pass</span>
                    <span class="k">elif</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">current</span><span class="p">,</span> <span class="s1">&#39;alters_data&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span>
                        <span class="n">current</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="k">try</span><span class="p">:</span>  <span class="c1"># method call (assuming no args required)</span>
                            <span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="p">()</span>
                        <span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
                            <span class="k">try</span><span class="p">:</span>
                                <span class="n">inspect</span><span class="o">.</span><span class="n">getcallargs</span><span class="p">(</span><span class="n">current</span><span class="p">)</span>
                            <span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>  <span class="c1"># arguments *were* required</span>
                                <span class="n">current</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span>  <span class="c1"># invalid method call</span>
                            <span class="k">else</span><span class="p">:</span>
                                <span class="k">raise</span>
        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
            <span class="n">template_name</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="s1">&#39;template_name&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">or</span> <span class="s1">&#39;unknown&#39;</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
                <span class="s2">&quot;Exception while resolving variable &#39;</span><span class="si">%s</span><span class="s2">&#39; in template &#39;</span><span class="si">%s</span><span class="s2">&#39;.&quot;</span><span class="p">,</span>
                <span class="n">bit</span><span class="p">,</span>
                <span class="n">template_name</span><span class="p">,</span>
                <span class="n">exc_info</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
            <span class="p">)</span>

            <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">&#39;silent_variable_failure&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span>
                <span class="n">current</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">string_if_invalid</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">raise</span>

        <span class="k">return</span> <span class="n">current</span>


<span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="c1"># Set this to True for nodes that must be first in the template (although</span>
    <span class="c1"># they can be preceded by text nodes.</span>
    <span class="n">must_be_first</span> <span class="o">=</span> <span class="kc">False</span>
    <span class="n">child_nodelists</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;nodelist&#39;</span><span class="p">,)</span>
    <span class="n">token</span> <span class="o">=</span> <span class="kc">None</span>

    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return the node rendered as a string.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">pass</span>

    <span class="k">def</span> <span class="nf">render_annotated</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Render the node. If debug is True and an exception occurs during</span>
<span class="sd">        rendering, the exception is annotated with contextual line information</span>
<span class="sd">        where it occurred in the template. For internal usage this method is</span>
<span class="sd">        preferred over using the render method directly.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">debug</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">&#39;template_debug&#39;</span><span class="p">):</span>
                <span class="n">e</span><span class="o">.</span><span class="n">template_debug</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">render_context</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">get_exception_info</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">token</span><span class="p">)</span>
            <span class="k">raise</span>

    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">yield</span> <span class="bp">self</span>

    <span class="k">def</span> <span class="nf">get_nodes_by_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetype</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a list of all nodes (within this node and its nodelist)</span>
<span class="sd">        of the given type</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">nodes</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetype</span><span class="p">):</span>
            <span class="n">nodes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">child_nodelists</span><span class="p">:</span>
            <span class="n">nodelist</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">nodelist</span><span class="p">:</span>
                <span class="n">nodes</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">nodelist</span><span class="o">.</span><span class="n">get_nodes_by_type</span><span class="p">(</span><span class="n">nodetype</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">nodes</span>


<span class="k">class</span> <span class="nc">NodeList</span><span class="p">(</span><span class="nb">list</span><span class="p">):</span>
    <span class="c1"># Set to True the first time a non-TextNode is inserted by</span>
    <span class="c1"># extend_nodelist().</span>
    <span class="n">contains_nontext</span> <span class="o">=</span> <span class="kc">False</span>

    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="n">bits</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">Node</span><span class="p">):</span>
                <span class="n">bit</span> <span class="o">=</span> <span class="n">node</span><span class="o">.</span><span class="n">render_annotated</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">bit</span> <span class="o">=</span> <span class="n">node</span>
            <span class="n">bits</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">force_text</span><span class="p">(</span><span class="n">bit</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">mark_safe</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">bits</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">get_nodes_by_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetype</span><span class="p">):</span>
        <span class="s2">&quot;Return a list of all nodes of the given type&quot;</span>
        <span class="n">nodes</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span>
            <span class="n">nodes</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">node</span><span class="o">.</span><span class="n">get_nodes_by_type</span><span class="p">(</span><span class="n">nodetype</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">nodes</span>


<span class="k">class</span> <span class="nc">TextNode</span><span class="p">(</span><span class="n">Node</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">s</span>

    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">rep</span> <span class="o">=</span> <span class="s2">&quot;&lt;</span><span class="si">%s</span><span class="s2">: </span><span class="si">%r</span><span class="s2">&gt;&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span>
        <span class="k">return</span> <span class="n">force_str</span><span class="p">(</span><span class="n">rep</span><span class="p">,</span> <span class="s1">&#39;ascii&#39;</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="s1">&#39;replace&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span>


<span class="k">def</span> <span class="nf">render_value_in_context</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Converts any value to a string to become part of a rendered template. This</span>
<span class="sd">    means escaping, if required, and conversion to a unicode object. If value</span>
<span class="sd">    is a string, it is expected to have already been translated.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">template_localtime</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">use_tz</span><span class="o">=</span><span class="n">context</span><span class="o">.</span><span class="n">use_tz</span><span class="p">)</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">localize</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">use_l10n</span><span class="o">=</span><span class="n">context</span><span class="o">.</span><span class="n">use_l10n</span><span class="p">)</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">force_text</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">autoescape</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">EscapeData</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">conditional_escape</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">value</span>


<span class="k">class</span> <span class="nc">VariableNode</span><span class="p">(</span><span class="n">Node</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filter_expression</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">filter_expression</span> <span class="o">=</span> <span class="n">filter_expression</span>

    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;&lt;Variable Node: </span><span class="si">%s</span><span class="s2">&gt;&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_expression</span>

    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">output</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_expression</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span>
            <span class="c1"># Unicode conversion can fail sometimes for reasons out of our</span>
            <span class="c1"># control (e.g. exception rendering). In that case, we fail</span>
            <span class="c1"># quietly.</span>
            <span class="k">return</span> <span class="s1">&#39;&#39;</span>
        <span class="k">return</span> <span class="n">render_value_in_context</span><span class="p">(</span><span class="n">output</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span>


<span class="c1"># Regex for token keyword arguments</span>
<span class="n">kwarg_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;(?:(\w+)=)?(.+)&quot;</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">token_kwargs</span><span class="p">(</span><span class="n">bits</span><span class="p">,</span> <span class="n">parser</span><span class="p">,</span> <span class="n">support_legacy</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A utility method for parsing token keyword arguments.</span>

<span class="sd">    :param bits: A list containing remainder of the token (split by spaces)</span>
<span class="sd">        that is to be checked for arguments. Valid arguments will be removed</span>
<span class="sd">        from this list.</span>

<span class="sd">    :param support_legacy: If set to true ``True``, the legacy format</span>
<span class="sd">        ``1 as foo`` will be accepted. Otherwise, only the standard ``foo=1``</span>
<span class="sd">        format is allowed.</span>

<span class="sd">    :returns: A dictionary of the arguments retrieved from the ``bits`` token</span>
<span class="sd">        list.</span>

<span class="sd">    There is no requirement for all remaining token ``bits`` to be keyword</span>
<span class="sd">    arguments, so the dictionary will be returned as soon as an invalid</span>
<span class="sd">    argument format is reached.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">bits</span><span class="p">:</span>
        <span class="k">return</span> <span class="p">{}</span>
    <span class="n">match</span> <span class="o">=</span> <span class="n">kwarg_re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
    <span class="n">kwarg_format</span> <span class="o">=</span> <span class="n">match</span> <span class="ow">and</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">kwarg_format</span><span class="p">:</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">support_legacy</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">{}</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="ow">or</span> <span class="n">bits</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;as&#39;</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">{}</span>

    <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="k">while</span> <span class="n">bits</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">kwarg_format</span><span class="p">:</span>
            <span class="n">match</span> <span class="o">=</span> <span class="n">kwarg_re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">):</span>
                <span class="k">return</span> <span class="n">kwargs</span>
            <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
            <span class="k">del</span> <span class="n">bits</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">bits</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="ow">or</span> <span class="n">bits</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;as&#39;</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">kwargs</span>
            <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">bits</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="k">del</span> <span class="n">bits</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span>
        <span class="n">kwargs</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">compile_filter</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">bits</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">kwarg_format</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;and&#39;</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">kwargs</span>
            <span class="k">del</span> <span class="n">bits</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">kwargs</span>
</pre></div>

          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">Jun 03, 2019</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    <a href="../../index.html" title="Module code" accesskey="U">up</a></div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>